#include "gui_filter.h"
#include "OSQuery.h"

#include <QToolTip>
#include <QMessageBox>
#include "FilterDialog.h"
#include "StarlabMainWindow.h"
#include "RichParameterSet.h"

void gui_filter::load(StarlabMainWindow* mainWindow){
    this->mainWindow = mainWindow;
    this->pluginManager = &(mainWindow->pluginManager);
    this->document = &mainWindow->document;
    this->drawArea = mainWindow->drawArea();
    
    /// Setup tooltips (mouse hover) for menu entries
    connect(mainWindow->filterMenu, SIGNAL(hovered(QAction*)), this, SLOT(showTooltip(QAction*)) );

    /// Fill the menu with plugin names and make connections
    foreach(FilterPlugin* plugin, pluginManager->filterPlugins.values()){
        QAction* action = plugin->action();
        mainWindow->filterMenu->addAction(action);
        
        // Action refers to this filter, so we can retrieve it later
        // QAction* action = new QAction(plugin->name(),plugin);
        
        
        /// Does the filter have an icon? Add it to the toolbar
        /// @todo add functionality to ModelFilter
        if(!action->icon().isNull())
            mainWindow->filterToolBar->addAction(action);

        /// Connect after it has been added        
        connect(action,SIGNAL(triggered()),this,SLOT(startFilter()));
    }
}

/// @todo have the tooltip always display with fixed width at the right hand side of the menu entry (not invasive)
void gui_filter::showTooltip(QAction* action){
    QString tip = action->toolTip();
    QToolTip::showText(QCursor::pos(), tip);
}

// It is splitted in two functions
// - startFilter that setup the dialogs and asks for parameters
// - executeFilter callback invoked when the params have been set up.
void gui_filter::startFilter() {
    // In order to avoid that a filter changes something assumed by the current editing tool,
    // before actually starting the filter we close the current editing tool (if any).
    /// @todo 
    // mainWindow->endEdit(); 
    // mainWindow->updateMenus();

    QAction* action = qobject_cast<QAction*>(sender());
    FilterPlugin* iFilter = qobject_cast<FilterPlugin*>(action->parent());
    if(iFilter) {
        
        /// Even though it's on the stack we associate it with the widget 
        /// in such a way that memory will get deleted when widget goes out 
        /// of scope
        RichParameterSet* parameters = new RichParameterSet();
        iFilter->initParameters(document, parameters, drawArea);
                
        /// Do I need the user input?
        if( parameters->isEmpty() ){
            /// No.. just use dummy parameters
            executeFilter(iFilter, parameters);
        } else {
            /// Create a new dialog & specify its settings
            FilterDialog* filterDialog = new FilterDialog(iFilter,parameters,mainWindow);
            /// Avoid parameter window from EVER losing focus
            filterDialog->setWindowFlags(mainWindow->windowFlags() | Qt::WindowStaysOnTopHint);
            /// Tell to run execute when user presses
            connect(filterDialog,SIGNAL(requestedExectuteFilter(FilterPlugin*,RichParameterSet*)), this,SLOT(executeFilter(FilterPlugin*,RichParameterSet*)));            
            /// Close window when parent windows closes
            connect(mainWindow, SIGNAL(destroyed()), filterDialog, SLOT(close()));
            /// Ask user for filter parameters.. will execute later
            filterDialog->showDialog();            
        }
    } 
}

void gui_filter::executeFilter(FilterPlugin* iFilter, RichParameterSet* parameters) {
    if(document->isEmpty()) return;
    if(!iFilter->isApplicable(document)) throw StarlabException("Filter is not applicable");

    /// @todo save the current filter and its parameters in the history
    // meshDoc()->filterHistory.actionList.append(qMakePair(iFilter->name(),params));
    
    /// @todo re-link the progress bar
    // qb->reset();    
    
    qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
    document->pushBusy();
        try{
            iFilter->applyFilter(document, parameters, mainWindow->drawArea());
            mainWindow->statusBarMessage("Filter '"+ iFilter->name() +"' Executed",5000);
        } catch(StarlabException& e){
            qApp->restoreOverrideCursor();
            /// Show a message box
            if(OSQuery::isMac()) 
                QMessageBox::warning(mainWindow, e.type(), e.type().toUpper() + ":\n\n" + e.message());
            else                 
                QMessageBox::warning(mainWindow, e.type(), e.message());
            /// Also log it to terminal
            qDebug() << "Filter error: " << e.message();     
        } catch (...) {
            qDebug() << "BAD EXCEPTION..";
        }
    document->popBusy();
    mainWindow->drawArea()->initRendering();
    qApp->restoreOverrideCursor();
}

Q_EXPORT_PLUGIN(gui_filter)
